﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Collision.Shapes;
using Util;
using LensflareGameFramework;
using Microsoft.Xna.Framework.Graphics;

namespace LensflareAIContest {
    public class Spaceship : GameEntity {
        Body body;
        CircleShape shape;
        Vector2 thrust = Vector2.Zero;
        float energy = 0.0f;
        float health;

		private Bar healthBar;
		private Bar energyBar;

		bool showHealthBar = true;
		bool showEnergyBar = true;
		bool showId = false;

        public int TeamIndex { get; protected set; }

        private static int nextID = 0;
        public int ID { get; protected set; }

        public static Texture2D Texture { get; set; }

        public Spaceship(LensflareAIContestGame game, Vector2 position, int teamIndex) : base(game) {
            ID = nextID++;
            TeamIndex = teamIndex;

            health = Game.Rules.Spaceship.HealthMax;
			healthBar = new Bar( game, 1.0f );
			energyBar = new Bar( game, energy / 1.0f );

            body = new Body(game.World);
            body.BodyType = BodyType.Dynamic;
            body.SleepingAllowed = false;
            body.LinearDamping = 0;
            body.AngularDamping = 0;
            body.SetTransform(position * Game.Rules.World.PhysicsSpaceScale, 0);
            body.UserData = this;

            shape = new CircleShape(Game.Rules.Spaceship.Radius * Game.Rules.World.PhysicsSpaceScale, 1.0f);

            new Fixture(body, shape);
        }

        protected override void Dispose() {
            Game.Teams[TeamIndex].Remove(this);
            body.UserData = null;
            body.Dispose();
            base.Dispose();
        }

        public Vector2 Position {
            get { return body.Position / Game.Rules.World.PhysicsSpaceScale; }
        }

        public Vector2 Velocity {
            get { return body.LinearVelocity; }
        }

        public Vector2 Thrust {
            get { return thrust; }
            set {
                thrust = value;
                if (thrust.Length() > 1.0f) {
                    thrust.Normalize();
                }
            }
        }

        public float Health { get { return health; } }

        public float Energy { get { return energy; } }

		public bool ShowHealthBar { get { return this.showHealthBar; } set { this.showHealthBar = value; } }
		public bool ShowEnergyBar { get { return this.showEnergyBar; } set { this.showEnergyBar = value; } }
		public bool ShowId { get { return this.showId; } set { this.showId = value; } }

        public override void Update(GameTime gameTime) {
            float elapsedSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds;

            body.ApplyForce(Thrust * Game.Rules.Spaceship.AccelerationMax * elapsedSeconds * Game.Rules.World.PhysicsSpaceScale);

            energy += Game.Rules.Spaceship.EnergyRegenerationRate * elapsedSeconds;			
            if (energy > 1.0f) {
                energy = 1.0f;
            }
			energyBar.Value = ( energy / 1.0f );
        }

        public void ApplyDamage(float damage) {
            float healthBeforeDamage = health;
            health -= damage;
            healthBar.Value = (health / Game.Rules.Spaceship.HealthMax);

            Game.Events.AddLast(new UnitEvent(UnitEvent.EventReason.Damaged, new UnitInfo(ID, TeamIndex, health, energy, Position, Velocity, Thrust)));

            if (health <= 0.0f) {
                if (healthBeforeDamage > 0.0f) {
                    Game.Events.AddLast(new UnitEvent(UnitEvent.EventReason.Destroyed, new UnitInfo(ID, TeamIndex, health, energy, Position, Velocity, Thrust)));
                }

                Entity.Remove(this);
            }
        }

        public void Shoot(Vector2 direction) {
            if(direction.Length() != 0.0f) {
                if (energy >= Game.Rules.Spaceship.EnergyNeededForShot) {
                    energy -= Game.Rules.Spaceship.EnergyNeededForShot;
					energyBar.Value = ( energy / 1.0f );

                    direction.Normalize();
                    const float distFactor = 1.01f; //makes sure that the projectile does not overlap with the shooting unit when spawned.
                    Vector2 projectilePosition = Position + direction * (Game.Rules.Spaceship.Radius + Game.Rules.Projectile.Radius) * distFactor;
                    Entity.Add(new Projectile(Game, projectilePosition, direction, this));
                }
            }
        }

        public override void Draw() {
            if (Game.Camera.OverlapsWorldShape(shape, body, Game.Rules.World.PhysicsSpaceScale)) {

                Vector2 screenPosition = Game.Camera.Project(Position);
                float zoomedRadius = Game.Rules.Spaceship.Radius * Game.Camera.Zoom;

				#region Bars

				if ( ShowEnergyBar || showHealthBar )
				{
                    float a = 0.7f;

					Vector2 healthBarSize = new Vector2( zoomedRadius * 2, zoomedRadius / 2 );
					Vector2 energyBarSize = new Vector2( healthBarSize.X, healthBarSize.Y * 0.8f );

					float distanceBetweenBars = 0.0f;
					float energyBarDistanceFromShip = 2.0f;

					Vector2 energyBarPosition = new Vector2( screenPosition.X - zoomedRadius,
															 screenPosition.Y - zoomedRadius - energyBarSize.Y - energyBarDistanceFromShip );

					Vector2 healthBarPosition = new Vector2( energyBarPosition.X,
															 energyBarPosition.Y - healthBarSize.Y - distanceBetweenBars );

					if ( ShowEnergyBar )
					{
                        energyBar.BorderColor = Game.PlayerColors[TeamIndex] * a;
                        energyBar.FillColor = Color.Yellow * a;
						energyBar.Position = energyBarPosition;
						energyBar.Size = energyBarSize;
						energyBar.Draw();
					}

					if ( ShowHealthBar )
					{
                        healthBar.BorderColor = Game.PlayerColors[TeamIndex] * a;
                        healthBar.FillColor = Game.PlayerColors[TeamIndex] * a;
						healthBar.Position = healthBarPosition;
						healthBar.Size = healthBarSize;
						healthBar.Draw();
					}
				}

				#endregion

                float layerDepth = Game.LayerManager.Depth((int)MainLayer.DynamicEntity);
                float textureZoom = Game.Rules.Spaceship.Radius * 2.0f / Texture.Width;
                Game.SpriteBatch.Draw(Texture, screenPosition, null, Game.PlayerColors[TeamIndex], 0, Texture.GetCenter(), Game.Camera.Zoom * textureZoom, SpriteEffects.None, layerDepth);

                /*
                Primitive2.DrawCircle(Game.SpriteBatch, screenPosition, zoomedRadius - 2, c1, false, layerDepth);
                Primitive2.DrawCircle(Game.SpriteBatch, screenPosition, zoomedRadius - 1, c2, false, layerDepth);
                Primitive2.DrawCircle(Game.SpriteBatch, screenPosition, zoomedRadius, c1, false, layerDepth);
                */

				if ( ShowId )
				{
					float textScale = Game.Camera.Zoom * 0.65f;
					string unitId = this.ID.ToString();
					Vector2 textSize = Game.DefaultFont.MeasureString( unitId ) * textScale;
					Game.SpriteBatch.DrawString( Game.DefaultFont, unitId, screenPosition - ( textSize / 2 ), Color.White, 0, Vector2.Zero, textScale, SpriteEffects.None, Game.LayerManager.Depth( (int)MainLayer.DynamicEntity ) );
				}
            }
        }
    }
}
